<?php
/**
 * Desc: 腾讯云直播流管理
 * Author: an
 * Date: 2021/12/11
 * Time: 11:20
 */


namespace App\Services\Tencent\Live;


use App\Services\Configs\DefaultService;
use App\Services\Tencent\BaseService;
use TencentCloud\Common\Credential;
use TencentCloud\Common\Exception\TencentCloudSDKException;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;
use TencentCloud\Live\V20180801\LiveClient;
use TencentCloud\Live\V20180801\Models\DescribeLiveForbidStreamListRequest;
use TencentCloud\Live\V20180801\Models\DescribeLiveStreamEventListRequest;
use TencentCloud\Live\V20180801\Models\DescribeLiveStreamOnlineListRequest;
use TencentCloud\Live\V20180801\Models\DescribeLiveStreamPublishedListRequest;
use TencentCloud\Live\V20180801\Models\DescribeLiveStreamStateRequest;
use TencentCloud\Live\V20180801\Models\DropLiveStreamRequest;
use TencentCloud\Live\V20180801\Models\ForbidLiveStreamRequest;
use TencentCloud\Live\V20180801\Models\ResumeLiveStreamRequest;

class StreamService extends BaseService
{
    protected $pushDomain;//推流域名
    protected $playDomain;//播放域名
    protected $pushKey;//推流鉴权key
    protected $playKey;//播放鉴权key

    public function __construct()
    {
        $config = $this->getConfig(DefaultService::TENCENT_LIVE);
        $this->secretId = $config['secretId'];
        $this->secretKey = $config['secretKey'];
        $this->pushDomain = $config['pushDomain'];
        $this->playDomain = $config['playDomain'];
        $this->pushKey = $config['pushKey'];
        $this->playKey = $config['playKey'];
    }

    /**
     * 获取推流地址
     * 如果不传key和过期时间，将返回不含防盗链的url
     * @param $streamName 区别不同推流地址的唯一流名称
     * @param null $time 过期时间 sample 2016-11-12 12:00:00。过期时间戳，单位是s
     * @return string
     * @author an
     * @date 2021-12-11 15:05
     */
    public function getPushUrl($streamName, $time = null)
    {
        if ($this->pushKey && $time) {
            $txTime = strtoupper(base_convert(strtotime($time), 10, 16));
            $txSecret = md5($this->pushKey . $streamName . $txTime);
            $ext_str = "?" . http_build_query(array(
                    "txSecret" => $txSecret,
                    "txTime" => $txTime
                ));
        }
        return "rtmp://" . $this->pushDomain . "/live/" . $streamName . (isset($ext_str) ? $ext_str : "");
    }

    /**
     * 获取播放地址
     * 如果不传key和过期时间，将返回不含防盗链的url
     * @param $streamName 区别不同推流地址的唯一流名称
     * @param null $time 过期时间 sample 2016-11-12 12:00:00。过期时间戳，单位是s
     * @return string urls
     * @author an
     * @date 2021-12-11 14:40
     */
    public function getPlayUrl($streamName, $time = null)
    {
        if ($this->playKey && $time) {
            $txTime = strtoupper(base_convert(strtotime($time), 10, 16));
            $txSecret = md5($this->playKey . $streamName . $txTime);
            $ext_str = "?" . http_build_query(array(
                    "txSecret" => $txSecret,
                    "txTime" => $txTime
                ));
        }
        return [
            "webrtc" => "webrtc://" . $this->playDomain . "/live/" . $streamName . (isset($ext_str) ? $ext_str : ""),
            "rtmp" => "rtmp://" . $this->playDomain . "/live/" . $streamName . (isset($ext_str) ? $ext_str : ""),
            "flv" => "http://" . $this->playDomain . "/live/" . $streamName . '.flv' . (isset($ext_str) ? $ext_str : ""),
            "hls" => "http://" . $this->playDomain . "/live/" . $streamName . '.m3u8' . (isset($ext_str) ? $ext_str : ""),
        ];
    }

    /**
     * 恢复直播推流
     * 恢复某条流的推流。
     * 默认接口请求频率限制：100次/秒。
     * @param $DomainName 推流域名。
     * @param $StreamName 流名称。
     * @param string $AppName 推流路径，与推流和播放地址中的AppName保持一致，默认为 live。
     * @return string|\TencentCloud\Live\V20180801\Models\ResumeLiveStreamResponse
     * @author an
     * @date 2021-12-12 13:45
     */
    public function resumeLiveStream($DomainName, $StreamName, $AppName = 'live')
    {
        try {

            $cred = new Credential($this->secretId, $this->secretKey);
            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint("live.tencentcloudapi.com");

            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);
            $client = new LiveClient($cred, "", $clientProfile);

            $req = new ResumeLiveStreamRequest();

            $params = array(
                "AppName" => $AppName,
                "DomainName" => $DomainName,
                "StreamName" => $StreamName
            );
            $req->fromJsonString(json_encode($params));

            $resp = $client->ResumeLiveStream($req);

            return $resp;
        } catch (TencentCloudSDKException $e) {
            return $e->getMessage();
        }
    }

    /**
     * 禁推直播流
     * @param $DomainName 推流域名。
     * @param $StreamName 流名称。
     * @param $ResumeTime 恢复流的时间。UTC 格式，例如：2018-11-29T19:00:00Z。
     * 注意：
     * 1. 默认禁播7天，且最长支持禁播90天。
     * 2. 北京时间值为 UTC 时间值 + 8 小时，格式按照 ISO 8601 标准表示，详见 ISO 日期格式说明。
     * @param null $Reason 禁推原因。
     * 注明：请务必填写禁推原因，防止误操作。
     * 长度限制：2048字节。
     * @param string $AppName 推流路径，与推流和播放地址中的AppName保持一致，默认为 live。
     * @return string|\TencentCloud\Live\V20180801\Models\ForbidLiveStreamResponse
     * @author an
     * @date 2021-12-12 13:38
     */
    public function forbidLiveStream($DomainName, $StreamName, $ResumeTime, $Reason, $AppName = 'live')
    {
        try {

            $cred = new Credential($this->secretId, $this->secretKey);
            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint("live.tencentcloudapi.com");

            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);
            $client = new LiveClient($cred, "", $clientProfile);

            $req = new ForbidLiveStreamRequest();

            $params = array(
                "AppName" => $AppName,
                "DomainName" => $DomainName,
                "StreamName" => $StreamName,
                "ResumeTime" => $ResumeTime,
                "Reason" => $Reason
            );
            $req->fromJsonString(json_encode($params));

            $resp = $client->ForbidLiveStream($req);

            return $resp;
        } catch (TencentCloudSDKException $e) {
            return $e->getMessage();
        }
    }

    /**
     * 断开直播流，断开推流连接，但可以重新推流
     * 默认接口请求频率限制：100次/秒。
     * @param $DomainName
     * @param $StreamName
     * @param string $AppName
     * @return string|\TencentCloud\Live\V20180801\Models\DropLiveStreamResponse
     * @author an
     * @date 2021-12-12 13:27
     */
    public function dropLiveStream($DomainName, $StreamName, $AppName = 'live')
    {
        try {

            $cred = new Credential($this->secretId, $this->secretKey);
            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint("live.tencentcloudapi.com");

            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);
            $client = new LiveClient($cred, "", $clientProfile);

            $req = new DropLiveStreamRequest();

            $params = array(
                "StreamName" => $StreamName,
                "DomainName" => $DomainName,
                "AppName" => $AppName
            );
            $req->fromJsonString(json_encode($params));

            $resp = $client->DropLiveStream($req);

            return $resp;
        } catch (TencentCloudSDKException $e) {
            return $e->getMessage();
        }
    }

    /**
     * 查询流状态
     * @param $DomainName 推流域名。
     * @param $StreamName 流名称。
     * @param string $AppName 推流路径，与推流和播放地址中的AppName保持一致，默认为 live。
     * @return \Exception|TencentCloudSDKException|\TencentCloud\Live\V20180801\Models\DescribeLiveStreamStateResponse
     * @author an
     * @date 2021-12-12 13:17
     */
    public function describeLiveStreamState($DomainName, $StreamName, $AppName = 'live')
    {
        try {

            $cred = new Credential($this->secretId, $this->secretKey);
            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint("live.tencentcloudapi.com");

            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);
            $client = new LiveClient($cred, "", $clientProfile);

            $req = new DescribeLiveStreamStateRequest();

            $params = array(
                "AppName" => $AppName,
                "DomainName" => $DomainName,
                "StreamName" => $StreamName
            );
            $req->fromJsonString(json_encode($params));

            $resp = $client->DescribeLiveStreamState($req);
            return $resp;
        } catch (TencentCloudSDKException $e) {
            return $e->getMessage();
        }
    }

    /**
     * 查询历史流列表
     * @param $DomainName 推流域名
     * @param $StartTime 结束时间。
     * UTC 格式，例如：2016-06-30T19:00:00Z。
     * 不超过当前时间。
     * 注意：EndTime和StartTime相差不可超过30天。
     * @param $EndTime 起始时间。
     * UTC 格式，例如：2016-06-29T19:00:00Z。
     * 最长支持查询60天内数据。
     * @param string $AppName 推流路径，与推流和播放地址中的 AppName 保持一致，默认为 live。不支持模糊匹配。
     * @param null $StreamName 流名称，支持模糊匹配。
     * @param null $PageNum 取得第几页。默认值：1。
     * @param null $PageSize 分页大小。
     * 最大值：100。
     * 取值范围：10~100 之前的任意整数。
     * 默认值：10。
     * @return \Exception|false|string|TencentCloudSDKException
     * @author an
     * @date 2021-12-12 12:50
     */
    public function describeLiveStreamPublishedList($DomainName, $StartTime, $EndTime, $AppName = 'live', $StreamName = null, $PageNum = null, $PageSize = null)
    {
        try {

            $cred = new Credential($this->secretId, $this->secretKey);
            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint("live.tencentcloudapi.com");

            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);
            $client = new LiveClient($cred, "", $clientProfile);

            $req = new DescribeLiveStreamPublishedListRequest();

            $params = array(
                "DomainName" => $DomainName,
                "EndTime" => $EndTime,
                "StartTime" => $StartTime,
                "AppName" => $AppName
            );
            $req->fromJsonString(json_encode($params));

            $resp = $client->DescribeLiveStreamPublishedList($req);

            return $resp;
        } catch (TencentCloudSDKException $e) {
            return $e->getMessage();
        }
    }

    /**
     * 查询直播中的流
     * @param $DomainName 推流域名。多域名用户需要填写 DomainName。
     * @param string $AppName 推流路径，与推流和播放地址中的 AppName 保持一致，默认为 live。多路径用户需要填写 AppName。
     * @param null $StreamName 流名称，用于精确查询
     * @param null $PageNum 取得第几页，默认1。
     * @param null $PageSize 每页大小，最大100。
     * 取值：10~100之间的任意整数。
     * 默认值：10。
     * @return string|\TencentCloud\Live\V20180801\Models\DescribeLiveStreamOnlineListResponse
     * @author an
     * @date 2021-12-12 13:53
     */
    public function describeLiveStreamOnlineList($DomainName, $AppName = 'live', $StreamName = null, $PageNum = null, $PageSize = null)
    {
        try {

            $cred = new Credential($this->secretId, $this->secretKey);
            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint("live.tencentcloudapi.com");

            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);
            $client = new LiveClient($cred, "", $clientProfile);

            $req = new DescribeLiveStreamOnlineListRequest();

            $params = array(
                "DomainName" => $DomainName,
                "AppName" => $AppName,
                "PageNum" => $PageNum,
                "PageSize" => $PageSize,
                "StreamName" => $StreamName
            );
            $req->fromJsonString(json_encode($params));

            $resp = $client->DescribeLiveStreamOnlineList($req);

            return $resp;
        } catch (TencentCloudSDKException $e) {
            return $e->getMessage();
        }
    }

    /**
     * 查询推断流事件
     * 该接口提供离线推断流记录查询功能，不可作为重要业务场景强依赖接口。
     * 该接口可通过使用IsFilter进行过滤，返回推流历史记录。
     * 默认接口请求频率限制：300次/秒。
     * @param $StartTime 起始时间。
     * UTC 格式，例如：2018-12-29T19:00:00Z。
     * 支持查询60天内的历史记录。
     * @param $EndTime 结束时间。
     * UTC 格式，例如：2018-12-29T20:00:00Z。
     * 不超过当前时间，且和起始时间相差不得超过30天。
     * @param string $AppName 推流路径，与推流和播放地址中的AppName保持一致，默认为 live。
     * @param null $DomainName 推流域名。
     * @param null $StreamName 流名称，不支持通配符（*）查询，默认模糊匹配。
     * 可使用IsStrict字段改为精确查询。
     * @param null $PageNum 取得第几页。
     * 默认值：1。
     * 注： 目前只支持10000条内的查询。
     * @param null $PageSize 分页大小。
     * 最大值：100。
     * 取值范围：1~100 之间的任意整数。
     * 默认值：10。
     * 注： 目前只支持10000条内的查询。
     * @param null $IsFilter 是否过滤，默认不过滤。
     * 0：不进行任何过滤。
     * 1：过滤掉开播失败的，只返回开播成功的。
     * @param null $IsStrict 是否精确查询，默认模糊匹配。
     * 0：模糊匹配。
     * 1：精确查询。
     * 注：使用StreamName时该参数生效。
     * @param null $IsAsc 是否按结束时间正序显示，默认逆序。
     * 0：逆序。
     * 1：正序。
     * @return bool|\TencentCloud\Live\V20180801\Models\DescribeLiveStreamEventListResponse
     * @author an
     * @date 2021-12-12 14:18
     */
    public function describeLiveStreamEventList($StartTime, $EndTime, $AppName = 'live', $DomainName = null, $StreamName = null, $PageNum = null, $PageSize = null, $IsFilter = null, $IsStrict = null, $IsAsc = null)
    {
        try {

            $cred = new Credential($this->secretId, $this->secretKey);
            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint("live.tencentcloudapi.com");

            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);
            $client = new LiveClient($cred, "", $clientProfile);

            $req = new DescribeLiveStreamEventListRequest();

            $params = array(
                "AppName" => $AppName,
                "DomainName" => $DomainName,
                "StreamName" => $StreamName,
                "StartTime" => $StartTime,
                "EndTime" => $EndTime,
                "PageNum" => $PageNum,
                "PageSize" => $PageSize,
                "IsFilter" => $IsFilter,
                "IsStrict" => $IsStrict,
                "IsAsc" => $IsAsc
            );
            $req->fromJsonString(json_encode($params));

            $resp = $client->DescribeLiveStreamEventList($req);

            return $resp;
        } catch (TencentCloudSDKException $e) {
            return false;
        }
    }

    /**
     * 获取禁推流列表
     * 该接口仅作为直播辅助查询接口，重要业务场景不可强依赖该接口。
     * 默认接口请求频率限制：100次/秒。
     * @param null $PageNum 取得第几页，默认1。
     * @param null $PageSize 每页大小，最大100。
     * 取值：1~100之前的任意整数。
     * 默认值：10。
     * @param null $StreamName 按流名称查询。
     * @return string|\TencentCloud\Live\V20180801\Models\DescribeLiveForbidStreamListResponse
     * @author an
     * @date 2021-12-12 14:43
     */
    public function describeLiveForbidStreamList($PageNum = null, $PageSize = null, $StreamName = null)
    {
        try {

            $cred = new Credential($this->secretId, $this->secretKey);
            $httpProfile = new HttpProfile();
            $httpProfile->setEndpoint("live.tencentcloudapi.com");

            $clientProfile = new ClientProfile();
            $clientProfile->setHttpProfile($httpProfile);
            $client = new LiveClient($cred, "", $clientProfile);

            $req = new DescribeLiveForbidStreamListRequest();

            $params = array(
                "PageNum" => $PageNum,
                "PageSize" => $PageSize,
                "StreamName" => $StreamName
            );
            $req->fromJsonString(json_encode($params));

            $resp = $client->DescribeLiveForbidStreamList($req);

            return $resp;
        } catch (TencentCloudSDKException $e) {
            return $e->getMessage();
        }
    }
}
